%%%----------------------------------------------------------------------
%%% File    : mod_disclaimer.erl
%%% Author  : Jorge Eduardo Cardona <jorge.cardona@fluidsignal.com>
%%% Purpose : Send legal disclaimer to users.
%%% Created : 6 Aug 2007 by Jorge Eduardo Cardona <jorge.cardona@fluidsignal.com>
%%% Id      : $Id: mod_disclaimer.erl ??? ????-??-?? ??:??:??? jcardona $
%%%----------------------------------------------------------------------

-module(mod_disclaimer).
-author('jorge.cardona@fluidsignal.com').

-behaviour(gen_mod).

-export([start/2,
	 stop/1,
	 add_disclaimer/1]).

-include("ejabberd.hrl").
-include("jlib.hrl").

-record(sessions,{parts,counters,timestamp}).
-record(disclaimer_state,{id,host}).

start(Host, _Opts) ->
    ejabberd_hooks:add(filter_packet, global,
		       ?MODULE, add_disclaimer, 50),
    mnesia:delete_table(sessions),
    mnesia:create_table(sessions,[{attributes,record_info(fields,sessions)}]),

    mnesia:delete_table(disclaimer_state),
    mnesia:create_table(disclaimer_state,[{attributes,record_info(fields,disclaimer_state)}]),
    
    ?DEBUG("Host: ~p~n",[Host]),
    F = fun()->
        mnesia:write({disclaimer_state,0,Host})
    end,
    mnesia:transaction(F),
    
    ok.

stop(Host) ->
    mnesia:delete_table(sessions),
    mnesia:delete_table(disclaimer_state),
    ejabberd_hooks:delete(filter_packet, global,
		       ?MODULE, add_disclaimer, 50),
    ok.


add_disclaimer(drop) ->
    drop;
add_disclaimer({From,To,Packet}) ->
    Message = gen_mod:get_module_opt( To#jid.lserver, ?MODULE, disclaimer_message, false),
    case Message of
        false ->
            {From,To,Packet};
        _ ->
            {xmlelement, Name, Attrs, Els} = Packet,
            [Type] = searchList(Attrs,"type"),
            [Packet2] = walk_packet([Packet],{From,To,Type}),
            {From,To,Packet2}
    end.
    

walk_packet([],Misc) ->
    [];
walk_packet([First| Rest],Misc) ->
    {From,To,Type} = Misc,
    F = fun() ->
        mnesia:read({disclaimer_state,0})
    end,
    {atomic,[{disclaimer_state,Id,Data}]}=mnesia:transaction(F),
    Time =  gen_mod:get_module_opt( Data, ?MODULE, disclaimer_time, 60),
    case First of
    {xmlelement, Name, Attrs, Els} ->
        if
        Name == "body" ->
            case sessionSearch({From,To,Type}) of
                {atomic,[{sessions,Parts,Counters,Timestamp}]} ->
                    if
                        Counters == {0,0} ->
                            sessionUpdate({From,To,Type}),
                            TimestampLimit = Timestamp - 1;
                        Counters == {1,0} ->
                            sessionUpdate({From,To,Type}),
                            sendDisclaimer({From,To,Type}),
                            TimestampLimit = nowSec() - Time;
                        Counters == {0,1} ->
                            sessionUpdate({From,To,Type}),
                            sendDisclaimer({From,To,Type}),
                            TimestampLimit = nowSec() - Time;
                        true ->
                            TimestampLimit = nowSec() - Time
                    end,
                    if
                        Timestamp > TimestampLimit ->
                            ok;
                        true ->
                            sessionUpdate({From,To,Type}),
                            sendDisclaimer({From,To,Type}),
                            sendDisclaimer({To,From,Type})
                    end;
                {atomic,[]} ->
                    sessionSave({From,To,Type}),
                    sendDisclaimer({From,To,Type}),
                    sessionUpdate({From,To,Type}),
                    sendDisclaimer({To,From,Type}),
                    sessionUpdate({To,From,Type});
                _ ->
                    ok
            end,
            Els2 = Els;
        Name == "gone" ->
            case sessionSearch({From,To,Type}) of
                {atomic,[{sessions,Parts,Counters,Timestamp}]} ->
                    sessionDelete({From,To,Type});
                _ ->
                    ok
            end,
            Els2 = Els;
        Name == "composing" ->
            case sessionSearch({From,To,Type}) of
                {atomic,[]} ->
                    sessionSave({From,To,Type}),
                    sendDisclaimer({To,From,Type});
                _ ->
                    ok
            end,
            Els2 = Els;
        Name == "presence" ->
            Els2 = Els;
        true ->
            Els2 = walk_packet(Els,{From,To,Type})
        end,
        First2 = {xmlelement, Name, Attrs,Els2},
        Rest2 = walk_packet(Rest,{From,To,Type});
    _ ->
        First2 = First,
        Rest2 = walk_packet(Rest,Misc)
    end,
    [First2]++Rest2.

orderParts({From,To}) ->
    User1 = From#jid.user++"@"++From#jid.server,
    User2 = To#jid.user++"@"++To#jid.server,
    if User1 < User2 ->
            Usero1 = User1, Usero2 = User2,
            Order = true;
        true ->
            Usero2 = User1, Usero1 = User2,
            Order = false
    end,
    {Usero1,Usero2,Order}.


sessionSearch({From,To,Type}) ->
    {User1,User2,Order} = orderParts({From,To}),
    F = fun() ->
        mnesia:read({sessions,{User1,User2,Type}})
    end,
    mnesia:transaction(F).

sessionDelete({From,To,Type}) ->
    {User1,User2,Order} = orderParts({From,To}),
    F = fun() ->
        mnesia:delete({sessions,{User1,User2,Type}})
    end,
    mnesia:transaction(F).

sessionSave({From,To,Type}) ->
    {User1,User2,Order} = orderParts({From,To}),
    F = fun()->
        mnesia:write({sessions,{User1,User2,Type},{0,0},nowSec()})
    end,
    mnesia:transaction(F).

sessionUpdate({From,To,Type}) ->
    {User1,User2,Order} = orderParts({From,To}),
    F = fun()->
        Res = mnesia:read({sessions,{User1,User2,Type}}),
        case Res of 
            [] ->
                [];
            _ ->
                [Data] = Res,
                {N1,N2}=Data#sessions.counters,
                if Order == true ->
                    mnesia:write({sessions,{User1,User2,Type},{N1,N2+1},nowSec()});
                true ->
                    mnesia:write({sessions,{User1,User2,Type},{N1+1,N2},nowSec()})
                end 
        end
    end,
    mnesia:transaction(F).

nowSec() ->
    {Mega,Sec,Micro} = now(),
    Mega*1000000+Sec.

sendDisclaimer({From,To,Type}) ->
    if
        Type == "groupchat" ->
            ok;
        true ->
            F = fun() ->
                mnesia:read({disclaimer_state,0})
            end,
            {atomic,[{disclaimer_state,Id,Data}]}=mnesia:transaction(F),
            Message = gen_mod:get_module_opt( Data, ?MODULE, disclaimer_message, false),
            if not (Message == false)->
                Attrs = [{"type",Type},{"id","legal"},{"to",To#jid.user++"@"++To#jid.server++"/"++To#jid.resource},{"from",From#jid.user++"@"++From#jid.server++"/"++From#jid.resource}],
                Els = [{xmlcdata,<<"\n">>},{xmlelement,"body",[],[{xmlcdata,list_to_binary(Message)}]}],
                Disclaimer = {xmlelement,"message",Attrs,Els},
                ejabberd_router:route(From,To,Disclaimer)
            end
    end.

searchList([],Query) ->
    [];
searchList([First|Rest],Query) ->
    case First of
        {Name,Value} ->
            if
                Name == Query ->
                    [Value]++searchList(Rest,Query);
                true ->
                    searchList(Rest,Query)
            end;
        _ ->
            searchList(Rest,Query)
    end.


